package auth

import (
	"encoding/base64"
	"fmt"
	"os"
	"time"

	"github.com/pquerna/otp/totp"
	"github.com/skip2/go-qrcode"
)

// GAUtil Google Authenticator工具类
type GAUtil struct{}

// NewGAUtil 创建Google Authenticator工具实例
func NewGAUtil() *GAUtil {
	return &GAUtil{}
}

// GenerateSecret 生成密钥
func (g *GAUtil) GenerateSecret() (string, error) {
	key, err := totp.Generate(totp.GenerateOpts{
		Issuer:      "GoPay跨境支付",
		AccountName: "user",
		SecretSize:  20, // 使用20字节的密钥
	})
	if err != nil {
		return "", fmt.Errorf("生成密钥失败: %v", err)
	}
	return key.Secret(), nil
}

// GenerateQRCode 生成二维码
// secret: 密钥
// email: 用户邮箱
// issuer: 发行者名称
// 返回二维码图片的base64字符串
func (g *GAUtil) GenerateQRCode(secret, email, issuer string) (string, error) {
	if issuer == "" {
		issuer = "GoPay跨境支付"
	}

	// 生成OTP URL，确保使用正确的格式
	otpURL := fmt.Sprintf("otpauth://totp/%s:%s?secret=%s&issuer=%s&algorithm=SHA1&digits=6&period=30",
		issuer,
		email,
		secret,
		issuer,
	)

	// 生成二维码，使用更高的纠错级别
	qr, err := qrcode.Encode(otpURL, qrcode.High, 256)
	if err != nil {
		return "", fmt.Errorf("生成二维码失败: %v", err)
	}

	// 将二维码转换为base64
	base64Str := fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(qr))
	return base64Str, nil
}

// VerifyToken 验证验证码
func (g *GAUtil) VerifyToken(secret, token string) bool {
	// 使用标准参数验证
	return totp.Validate(token, secret)
}

// GetCurrentToken 获取当前验证码
func (g *GAUtil) GetCurrentToken(secret string) (string, error) {
	// 使用标准参数生成验证码
	code, err := totp.GenerateCode(secret, time.Now())
	if err != nil {
		return "", fmt.Errorf("获取验证码失败: %v", err)
	}
	return code, nil
}

// SaveQRCodeToFile 将二维码保存为文件
// secret: 密钥
// email: 用户邮箱
// issuer: 发行者名称
// filename: 保存的文件名
func (g *GAUtil) SaveQRCodeToFile(secret, email, issuer, filename string) error {
	if issuer == "" {
		issuer = "GoPay跨境支付"
	}

	// 生成OTP URL，使用标准格式
	otpURL := fmt.Sprintf("otpauth://totp/%s:%s?secret=%s&issuer=%s&algorithm=SHA1&digits=6&period=30",
		issuer,
		email,
		secret,
		issuer,
	)

	// 生成二维码，使用更高的纠错级别
	qr, err := qrcode.Encode(otpURL, qrcode.High, 256)
	if err != nil {
		return fmt.Errorf("生成二维码失败: %v", err)
	}

	// 保存为文件
	err = os.WriteFile(filename, qr, 0644)
	if err != nil {
		return fmt.Errorf("保存二维码文件失败: %v", err)
	}

	return nil
}
